package com.example.auth.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.auth.mapper.RegionMapper;
import com.example.auth.model.dto.RegionDTO;
import com.example.auth.model.entity.Region;
import com.example.auth.service.MinioService;
import com.example.auth.service.RegionService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 省市区街道服务实现类
 */
@Slf4j
@Service
public class RegionServiceImpl extends ServiceImpl<RegionMapper, Region> implements RegionService {

    @Value("${file.upload.path:uploads}")
    private String uploadPath;
    
    @Value("${file.access.path:http://localhost:8081/uploads/}")
    private String accessPath;
    
    @Autowired
    private MinioService minioService;

    /**
     * 递归获取树形结构的区域数据
     */
    @Override
    public List<RegionDTO> getRegionTree(Long parentId) {
        // 获取第一级数据
        List<Region> regions = baseMapper.findByParentId(parentId);
        List<RegionDTO> result = regions.stream().map(this::convertToDTO).collect(Collectors.toList());
        
        // 递归加载子节点
        for (RegionDTO dto : result) {
            if (dto.getHasChildren()) {
                dto.setChildren(getRegionTree(dto.getId()));
            } else {
                dto.setChildren(new ArrayList<>());
            }
        }
        
        return result;
    }

    /**
     * 获取子区域列表
     */
    @Override
    public List<RegionDTO> getRegionList(Long parentId) {
        List<Region> regions = baseMapper.findByParentId(parentId);
        return regions.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 获取所有区域的扁平化列表
     */
    @Override
    public List<RegionDTO> getAllRegions() {
        // 查询所有区域
        List<Region> regions = baseMapper.selectList(null);
        return regions.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    /**
     * 保存区域信息
     */
    @Override
    @Transactional
    public RegionDTO saveRegion(RegionDTO regionDTO) {
        // 检查编码是否已存在
        int count = baseMapper.countByCode(regionDTO.getCode(), regionDTO.getId());
        if (count > 0) {
            throw new RuntimeException("区域编码已存在");
        }
        
        Region region = new Region();
        BeanUtils.copyProperties(regionDTO, region);
        
        // 如果不是街道级别，清除经纬度和图片信息
        if (region.getLevel() != null && region.getLevel() != 4) {
            region.setLongitude(null);
            region.setLatitude(null);
            region.setImageUrl(null);
            region.setAdType(null);
            region.setAdRealImageUrl(null);
            region.setArea(null);
        }
        
        LocalDateTime now = LocalDateTime.now();
        if (region.getId() == null) {
            // 新增
            region.setCreateTime(now);
            region.setUpdateTime(now);
            baseMapper.insert(region);
        } else {
            // 修改
            region.setUpdateTime(now);
            baseMapper.updateById(region);
        }
        
        RegionDTO result = convertToDTO(region);
        result.setHasChildren(false); // 新增的节点肯定没有子节点
        return result;
    }

    /**
     * 根据ID查询区域
     */
    @Override
    public RegionDTO getRegionById(Long id) {
        Region region = baseMapper.selectById(id);
        if (region == null) {
            return null;
        }
        
        RegionDTO dto = convertToDTO(region);
        // 检查是否有子节点
        int childCount = baseMapper.countChildrenById(id);
        dto.setHasChildren(childCount > 0);
        
        return dto;
    }

    /**
     * 删除区域（如果有子区域则不允许删除）
     */
    @Override
    @Transactional
    public boolean deleteRegion(Long id) {
        // 检查是否有子节点
        int childCount = baseMapper.countChildrenById(id);
        if (childCount > 0) {
            throw new RuntimeException("该区域下有子区域，不能删除");
        }
        
        // 执行删除操作
        return baseMapper.deleteById(id) > 0;
    }

    /**
     * 上传街道图片
     */
    @Override
    public String uploadStreetImage(MultipartFile file, Long streetId) {
        // 检查街道是否存在
        Region street = baseMapper.selectById(streetId);
        if (street == null) {
            throw new RuntimeException("街道不存在");
        }
        
        // 检查是否是街道级别
        if (street.getLevel() != 4) {
            throw new RuntimeException("只有街道级别才能上传图片");
        }
        
        try {
            // 生成文件名
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName = UUID.randomUUID().toString() + extension;
            String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 构建MinIO对象名称
            String objectName = "region_images/" + dateDir + "/" + newFileName;
            
            // 上传到MinIO
            String imageUrl = minioService.uploadFile(file, objectName);
            
            // 更新街道图片URL
            street.setImageUrl(imageUrl);
            street.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(street);
            
            return imageUrl;
        } catch (Exception e) {
            throw new RuntimeException("上传图片失败: " + e.getMessage());
        }
    }

    /**
     * 删除街道图片
     */
    @Override
    public boolean deleteStreetImage(Long streetId) {
        // 检查街道是否存在
        Region street = baseMapper.selectById(streetId);
        if (street == null) {
            return false;
        }
        
        // 检查是否是街道级别
        if (street.getLevel() != 4) {
            throw new RuntimeException("只有街道级别才有图片");
        }
        
        // 删除原图片文件
        if (StringUtils.hasText(street.getImageUrl())) {
            try {
                // 从MinIO中删除文件
                String objectName = extractObjectNameFromUrl(street.getImageUrl());
                if (objectName != null) {
                    minioService.deleteFile(objectName);
                }
            } catch (Exception e) {
                // 删除文件失败不影响数据库操作
                log.warn("删除MinIO文件失败: {}", e.getMessage());
            }
        }
        
        // 更新数据库
        street.setImageUrl(null);
        street.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(street) > 0;
    }

    /**
     * 上传广告实位图
     */
    @Override
    public String uploadAdRealImage(MultipartFile file, Long streetId) {
        // 检查街道是否存在
        Region street = baseMapper.selectById(streetId);
        if (street == null) {
            throw new RuntimeException("街道不存在");
        }
        
        // 检查是否是街道级别
        if (street.getLevel() != 4) {
            throw new RuntimeException("只有街道级别才能上传广告实位图");
        }
        
        try {
            // 生成文件名
            String originalFilename = file.getOriginalFilename();
            String extension = originalFilename.substring(originalFilename.lastIndexOf("."));
            String newFileName = UUID.randomUUID().toString() + extension;
            String dateDir = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            
            // 构建MinIO对象名称
            String objectName = "ad_real_images/" + dateDir + "/" + newFileName;
            
            // 上传到MinIO
            String imageUrl = minioService.uploadFile(file, objectName);
            
            // 更新街道广告实位图URL
            street.setAdRealImageUrl(imageUrl);
            street.setUpdateTime(LocalDateTime.now());
            baseMapper.updateById(street);
            
            return imageUrl;
        } catch (Exception e) {
            throw new RuntimeException("上传广告实位图失败: " + e.getMessage());
        }
    }

    /**
     * 删除广告实位图
     */
    @Override
    public boolean deleteAdRealImage(Long streetId) {
        // 检查街道是否存在
        Region street = baseMapper.selectById(streetId);
        if (street == null) {
            return false;
        }
        
        // 检查是否是街道级别
        if (street.getLevel() != 4) {
            throw new RuntimeException("只有街道级别才有广告实位图");
        }
        
        // 删除原图片文件
        if (StringUtils.hasText(street.getAdRealImageUrl())) {
            try {
                // 从MinIO中删除文件
                String objectName = extractObjectNameFromUrl(street.getAdRealImageUrl());
                if (objectName != null) {
                    minioService.deleteFile(objectName);
                }
            } catch (Exception e) {
                // 删除文件失败不影响数据库操作
                log.warn("删除MinIO广告实位图文件失败: {}", e.getMessage());
            }
        }
        
        // 更新数据库
        street.setAdRealImageUrl(null);
        street.setUpdateTime(LocalDateTime.now());
        return baseMapper.updateById(street) > 0;
    }

    /**
     * 获取完整的区域路径（从省到当前级别）
     */
    @Override
    public List<RegionDTO> getRegionPath(Long id) {
        List<Region> path = baseMapper.findPath(id);
        return path.stream().map(this::convertToDTO).collect(Collectors.toList());
    }
    
    /**
     * 将实体转换为DTO
     */
    private RegionDTO convertToDTO(Region region) {
        if (region == null) {
            return null;
        }
        
        RegionDTO dto = new RegionDTO();
        BeanUtils.copyProperties(region, dto);
        
        // 确保布尔值字段以布尔类型返回
        dto.setIsStreet(region.getIsStreet() != null ? region.getIsStreet() : region.getLevel() == 4);
        dto.setHasChildren(region.getHasChildren() != null ? region.getHasChildren() : false);
        
        return dto;
    }

    /**
     * 从URL中提取对象名称
     */
    private String extractObjectNameFromUrl(String url) {
        if (!StringUtils.hasText(url)) {
            return null;
        }
        
        try {
            // 如果URL包含region_images/，提取从region_images/开始的部分
            if (url.contains("region_images/")) {
                return url.substring(url.indexOf("region_images/"));
            }
            // 如果URL包含ad_real_images/，提取从ad_real_images/开始的部分  
            if (url.contains("ad_real_images/")) {
                return url.substring(url.indexOf("ad_real_images/"));
            }
            return null;
        } catch (Exception e) {
            log.warn("提取对象名称失败: {}", e.getMessage());
            return null;
        }
    }
} 